package com.my.study.redisson.register;

import com.my.study.redisson.register.health.RegisterHealth;
import com.my.study.redisson.register.health.impl.RegisterClientHealth;
import com.my.study.redisson.register.health.impl.RegisterServerHealth;
import com.my.study.redisson.register.node.RegisterNode;
import com.my.study.redisson.register.properties.RegisterProperties;
import com.my.study.util.NamedThreadFactory;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 默认的上下文
 *
 * @author: yidujun
 * @create: 2021/11/23 11:24
 */
@Component
public class DefaultRegisterContext implements RegisterContext, DisposableBean, ApplicationContextAware {

    private ApplicationContext applicationContext;

    private RegisterProperties registerProperties;

    private RedissonClient redissonClient;

    private RegisterNode selfRegisterNode;

    private Map<String, RegisterNode> registerNodeMap = new ConcurrentHashMap<>(8);

    private final ScheduledExecutorService clientExpireExecutor;

    private final ScheduledExecutorService serverExpireExecutor;

    public DefaultRegisterContext() {
        this.clientExpireExecutor = new ScheduledThreadPoolExecutor(1,
                new NamedThreadFactory("ClientExpireTimer", true));
        this.serverExpireExecutor = new ScheduledThreadPoolExecutor(1,
                new NamedThreadFactory("ServerExpireTimer", true));
    }

    public void init() {
        // 1、监控
        openHeartbeatTasks();

        // 注册到注册中心

    }

    public void openHeartbeatTasks() {
        int serverExpirePeriod = registerProperties.getServerExpirePeriod();
        int clientExpirePeriod = registerProperties.getClientExpirePeriod();

        RegisterHealth clientHealth = new RegisterClientHealth(this);
        RegisterHealth serverHealth = new RegisterServerHealth(this);

        RegisterNodeRefreshTask serverTask = new RegisterNodeRefreshTask(serverHealth);
        RegisterNodeRefreshTask clientTask = new RegisterNodeRefreshTask(clientHealth);
        serverExpireExecutor.scheduleWithFixedDelay(serverTask, serverExpirePeriod, serverExpirePeriod, TimeUnit.MILLISECONDS);
        clientExpireExecutor.scheduleWithFixedDelay(clientTask, clientExpirePeriod, clientExpirePeriod, TimeUnit.MILLISECONDS);
    }


    public void setRegisterProperties(RegisterProperties registerProperties) {
        this.registerProperties = registerProperties;
    }

    @Override
    public RegisterProperties getRegisterProperties() {
        return this.registerProperties;
    }

    @Override
    public RedissonClient getRedissonClient() {
        return redissonClient;
    }

    @Override
    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }


    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }


    @Override
    public void destroy() throws Exception {
        System.out.println("destroy...");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("init... " + applicationContext);
        this.applicationContext = applicationContext;
    }
}
